

function _registerEvent(target: any, eventType:string, cb:any) {
    if (target.addEventListener) {
        target.addEventListener(eventType, cb);
        return {
            remove: function () {
                target.removeEventListener(eventType, cb);
            }
        };
    } else {
        target.attachEvent(eventType, cb);
        return {
            remove: function () {
                target.detachEvent(eventType, cb);
            }
        };
    }
}

function _createHiddenIframe(target:HTMLElement, uri:string) {
    var iframe:HTMLIFrameElement = document.createElement("iframe");
    iframe.src = uri;
    iframe.id = "hiddenIframe";
    iframe.style.display = "none";
    target.appendChild(iframe);

    return iframe;
}

/**
 * @description 此方法调用有bug，当设置为默认调用时会不能触发Blur方法
 *
 * @param {*} uri
 * @param {*} failCb
 * @param {*} successCb
 */
function openUriWithHiddenFrame(uri:string, failCb:Function, successCb:Function) {
    var timeout = setTimeout(function () {
        failCb();
        handler.remove();
    }, 1000);
    var iframe:any = document.querySelector("#hiddenIframe");
    if (!iframe) {
        iframe = _createHiddenIframe(document.body, "about:blank");
    }
    var handler = _registerEvent(window, "blur", onBlur);
    function onBlur() {
        clearTimeout(timeout);
        handler.remove();
        successCb();
    }
    iframe.contentWindow.location.href = uri;
}

/**
 *  @description 此方法调用有bug，当设置为默认调用时会不能触发Blur方法
 *
 * @param {*} uri
 * @param {*} failCb
 * @param {*} successCb
 */
function openUriWithTimeoutHack(uri:string, failCb:Function, successCb:Function) {
    var timeout = setTimeout(function () {
        failCb();
        handler.remove();
    }, 1000);
    //handle page running in an iframe (blur must be registered with top level window)
    var target:any = window;
    while (target != target.parent) {
        target = target.parent;
    }
    var handler = _registerEvent(target, "blur", onBlur);
    function onBlur() {
        clearTimeout(timeout);
        handler.remove();
        successCb();
    }
    window.location.href = uri;
}
function openUriUsingFirefox(uri:string, failCb:Function, successCb:Function) {
    var iframe:any = document.querySelector("#hiddenIframe");
    if (!iframe) {
        iframe = _createHiddenIframe(document.body, "about:blank");
    }
    try {
        iframe.contentWindow.location.href = uri;
        successCb();
    } catch (e) {
        failCb();
    }
}

function openUriUsingIEInOlderWindows(uri:string, failCb:Function, successCb:Function) {
    if (getInternetExplorerVersion() === 10) {
        openUriUsingIE10InWindows7(uri, failCb, successCb);
    } else if (getInternetExplorerVersion() === 9 || getInternetExplorerVersion() === 11) {
        openUriWithHiddenFrame(uri, failCb, successCb);
    } else {
        openUriInNewWindowHack(uri, failCb, successCb);
    }
}

function openUriUsingIE10InWindows7(uri:string, failCb:Function, successCb:Function) {
    var timeout = setTimeout(failCb, 1000);
    window.addEventListener("blur", function () {
        clearTimeout(timeout);
        successCb();
    });
    var iframe:any = document.querySelector("#hiddenIframe");
    if (!iframe) {
        iframe = _createHiddenIframe(document.body, "about:blank");
    }
    try {
        iframe.contentWindow.location.href = uri;
    } catch (e) {
        failCb();
        clearTimeout(timeout);
    }
}

function openUriInNewWindowHack(uri:string, failCb:Function, successCb:Function) {
    var myWindow = window.open('', '', 'width=0,height=0');
    myWindow.document.write("<iframe src='" + uri + "'></iframe>");
    setTimeout(function () {
        try {
            // myWindow.location.href;
            myWindow.setTimeout("window.close()", 1000);
            successCb();
        } catch (e) {
            myWindow.close();
            failCb();
        }
    }, 1000);
}

function openUriWithMsLaunchUri(uri: string, failCb: MSLaunchUriCallback, successCb: MSLaunchUriCallback) {
    navigator.msLaunchUri(uri,
        successCb,
        failCb
    );
}

function checkBrowser() {
    var isOpera = navigator.userAgent.indexOf(' OPR/') >= 0;
    var ua = navigator.userAgent.toLowerCase();
    return {
        isOpera: isOpera,
        isFirefox: typeof window.InstallTrigger !== 'undefined',
        isSafari: (~ua.indexOf('safari') && !~ua.indexOf('chrome')) || Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0,
        isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,
        isChrome: !!window.chrome && !isOpera,
        isIE: /*@cc_on!@*/false || !!document.DOCUMENT_NODE // At least IE6
    }
}

/**
 *@description 判断ie老版本浏览器（包含网景浏览器）
 *
 * @returns
 */
function getInternetExplorerVersion() {
    var rv = -1;
    if (navigator.appName === "Microsoft Internet Explorer") {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null)
            rv = parseFloat(RegExp.$1);
    }
    else if (navigator.appName === "Netscape") {
        var ua = navigator.userAgent;
        var re = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null) {
            rv = parseFloat(RegExp.$1);
        }
    }
    return rv;
}
/**
 *
 *
 * @export
 * @param {*} uri 传入的url
 * @param {*} failCb   失败回调函数
 * @param {*} successCb 成功的回调函数
 * @param {*} unsupportedCb 不支持的浏览器回调函数
 */
export default function (uri: string, failCb?:MSLaunchUriCallback, successCb?:MSLaunchUriCallback, unsupportedCb?:MSLaunchUriCallback) {
    function failCallback() {
        failCb && failCb();
    }
    function successCallback() {
        successCb && successCb();
    }
    function unsupportedCallback(){
        unsupportedCb&&unsupportedCb()
    }
    if (!!navigator.msLaunchUri) {
        openUriWithMsLaunchUri(uri, failCallback, successCallback);
    } else {
        var browser = checkBrowser();
        if (browser.isChrome || browser.isIOS || browser.isFirefox) {
            openUriUsingFirefox(uri, failCallback, successCallback);
        } else if (browser.isIE) {
            openUriUsingIEInOlderWindows(uri, failCallback, successCallback);
        } else if (browser.isSafari) {
            openUriWithHiddenFrame(uri, failCallback, successCallback);
        } else {
            unsupportedCallback();
        }
    }
}